package com.lanyou.esb.cook.proxy.redis.proxy.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.exceptions.JedisException;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.lanyou.esb.cook.proxy.common.Constants;
import com.lanyou.esb.cook.proxy.common.Constants4Redis;
import com.lanyou.esb.cook.proxy.entity.Token;
import com.lanyou.esb.cook.proxy.redis.JedisPoolUtils;
import com.lanyou.esb.cook.proxy.redis.proxy.base.BaseHashJedisProxy;

/**
 * 接口令牌Redis操作代理
 * 
 * @author Davey.wu
 */
public class TokenJedisProxy extends BaseHashJedisProxy<Token> {
	/** 服务测试接口令牌HASH键 **/
	public static final String HASH_KEY_FOR_TEST_TOKEN = Constants4Redis.REDIS_HASH_KEY_TOKEN_TEST;

	public TokenJedisProxy() {
		this.setKey(Constants4Redis.REDIS_HASH_KEY_TOKEN);

		/** field的组成：系统编码，接口编码，接口版本，调用方系统编码 **/
		Map<String, Integer> keyFields = new HashMap<>();
		keyFields.put(Constants.SYSTEM_CODE, 0);
		keyFields.put(Constants.INTERFACE_CODE, 1);
		keyFields.put(Constants.INTERFACE_VERSION, 2);
		keyFields.put(Constants.CALL_SYSTEM_CODE, 3);
		this.setFields(keyFields);
	}

	@Override
	public long hset(String key, Token target) throws JedisException,
			JsonProcessingException {
		String json = this.toJson(target);
		long result = 0;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return 0l;
		}
		boolean broken = false;
		try {
			Pipeline pipe = jedis.pipelined();
			// 服务请求会用到
			pipe.hset(this.getKey(), key, json);
			// 申请访问令牌会用到
			pipe.hset(this.getKey(), this.getAppKey(target), json);
			pipe.sync();
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		return result;
	}

	@Override
	public void loadHashAll(List<Token> list) throws JedisException,
			JsonProcessingException {
		if (list == null || list.isEmpty()) {
			return;
		}
		Map<String, String> jsons = new HashMap<>(list.size());
		for (Token token : list) {
			jsons.put(token.getId(), this.toJson(token));
		}
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return;
		}
		boolean broken = false;
		try {
			Pipeline p = jedis.pipelined();
			for (Token t : list) {
				p.hset(this.getKey(), this.getKeyFromObject(t),
						jsons.get(t.getId()));
				p.hset(this.getKey(), this.getAppKey(t), jsons.get(t.getId()));
			}
			p.sync();
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
	}

	@Override
	public Map<String, String> getKeyMap(Token token) {
		Map<String, String> map = new HashMap<>(4);
		map.put(Constants.SYSTEM_CODE, token.getPubSystemCode());
		map.put(Constants.INTERFACE_CODE, token.getIfCode());
		map.put(Constants.INTERFACE_VERSION, token.getIfVersion());
		map.put(Constants.CALL_SYSTEM_CODE, token.getCallSytemCode());
		return map;
	}

	/**
	 * 获取测试令牌
	 * 
	 * @param key
	 *            ：键
	 * @return
	 * @throws JedisException
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws IOException
	 */
	public Token getHash4TestToken(String key) throws JedisException,
			JsonParseException, JsonMappingException, IOException {
		Token target = null;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return null;
		}
		boolean broken = false;
		String targetStr = "";
		try {
			targetStr = jedis.hget(HASH_KEY_FOR_TEST_TOKEN, key);

		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		if (StringUtils.isNotBlank(targetStr)) {
			target = fromJson(targetStr);
		}
		return target;
	}

	/**
	 * 保存测试访问令牌
	 * 
	 * @param key
	 *            ：键
	 * @param value
	 *            ：值
	 * @return
	 * @throws JsonProcessingException
	 */
	public long saveHash4TestToken(String key, Token value)
			throws JedisException, JsonProcessingException {
		String json = this.toJson(value);
		long result = 0;
		Jedis jedis = JedisPoolUtils.getJedis();
		if (jedis == null) {
			return 0l;
		}
		boolean broken = false;
		try {
			result = jedis.hset(HASH_KEY_FOR_TEST_TOKEN, key, json);
		} catch (Exception e) {
			broken = true;
		} finally {
			JedisPoolUtils.returnRes(jedis, broken);
		}
		return result;
	}

	/**
	 * 根据密钥查找令牌的键值
	 * 
	 * @param token
	 *            ：令牌
	 * @return
	 */
	private String getAppKey(Token token) {
		return token.getAppKey() + KEY_SEPARATOR + token.getPubSystemCode()
				+ KEY_SEPARATOR + token.getIfCode() + KEY_SEPARATOR
				+ token.getIfVersion();
	}
}
